using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Management.Automation;
using System.Text;
using System.Xml;

using Pscx.Commands.Internal;

namespace Pscx.Commands.Xml
{
    public abstract class XmlCommandBase : PscxInputObjectPathCommandBase
    {
        protected abstract void ProcessXmlReader(XmlReader xmlReader, XmlWriter xmlWriter);

        protected virtual XmlReaderSettings XmlReaderSettings
        {
            get
            {
                XmlReaderSettings readerSettings = new XmlReaderSettings();

                readerSettings.CloseInput = true;
                readerSettings.IgnoreWhitespace = true;

                return readerSettings;
            }
        }

        protected virtual XmlWriterSettings XmlWriterSettings
        {
            get
            {
                XmlWriterSettings writerSettings = new XmlWriterSettings();

                writerSettings.CloseOutput = true;
                writerSettings.Indent = true;

                return writerSettings;
            }
        }

        protected override PscxInputObjectPathSettings InputSettings
        {
            get
            {
                PscxInputObjectPathSettings settings = base.InputSettings;
                settings.ProcessDirectoryInfoAsPath = false;

                return settings;
            }
        }

        protected override void BeginProcessing()
        {
            RegisterInputType<String>(ProcessString);
            RegisterInputType<TextReader>(ProcessTextReader);
            RegisterInputType<XmlNode>(ProcessXmlNode);
            RegisterInputType<XmlReader>(ProcessXmlReader);

            base.BeginProcessing();
        }

        protected override void ProcessPath(string path)
        {
            try
            {
                using (StreamReader reader = File.OpenText(path))
                {
                    ProcessTextReader(reader);
                }
            }
            catch (Exception exc)
            {
                WriteError(PscxErrorRecord.FileError(exc, path));
            }
        }

        private void ProcessString(string xmlText)
        {
            using (StringReader stringReader = new StringReader(xmlText))
            {
                ProcessTextReader(stringReader);
            }
        }

        private void ProcessTextReader(TextReader textReader)
        {
            using (XmlReader xmlReader = XmlReader.Create(textReader, XmlReaderSettings))
            {
                ProcessXmlReader(xmlReader);
            }
        }

        private void ProcessXmlNode(XmlNode node)
        {
            using (XmlNodeReader xmlReader = new XmlNodeReader(node))
            {
                ProcessXmlReader(xmlReader);
            }
        }

        private void ProcessXmlReader(XmlReader reader)
        {
          using (StringWriter stringWriter = new StringWriter())
            {
                using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, XmlWriterSettings))
                {
                    ProcessXmlReader(reader, xmlWriter);
                }

                WriteObject(stringWriter.ToString());
            }
        }
    }
}
